// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// e [author] rhyme_lph
// o [email]  rhymelph@gmail.com
// i [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/coa_entity.dart';
import 'package:finance_app/src/entities/company_entity.dart';
import 'package:finance_app/src/entities/company_financial_year_entity.dart';
import 'package:finance_app/src/http_service/http_coa_service.dart';
import 'package:finance_app/src/http_service/http_company_service.dart';
import 'package:finance_app/src/mixin/check_plan_mixin.dart';
import 'package:finance_app/src/mixin/scroll_to_hide_mixin.dart';
import 'package:finance_app/src/mixin/search_data_list_mixin.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/date_time_select_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/got_it_tip_bottom_sheet.dart';
import 'package:flutter/material.dart';

class ChartOfAccountsProvider extends BaseProvider<List<CoaByGroupEntity>>
    with SearchDataListMixin, ScrollToHideMixin, CheckPlanMixin {
  List<String> menuList = ['Set Opening Balance', 'Close Current FY'];

  List<int> parentIDs = [];
  bool isSelectMode = false;

  DateTime asAt = DateTime.parse(Config.currentFY.endDate);

  int editId;

  @override
  Future get dataFuture => HttpCoaService.coaNewList(
        as_at: DateTimeUtils.formatDateTime(asAt, 'yyyy-MM-dd'),
      );

  double debitTotal = 0.00;

  double creditTotal = 0.00;

  double difference = 0.00;

  @override
  void searchRefreshData(searchData) {}

  void onNavAdd() {
    if (isPlanExpired()) return;
    Routes.navigateTo(RouterGenProviders.newAccountPage);
  }

  void formatTotal(List<CoaByGroupEntity> d, {bool isUpdate = false}) {
    double _dTotal = 0.0;
    double _cTotal = 0.0;
    for (final item in d) {
      for (final item1 in item?.coaAccountDetail) {
        if (item1.accountCode == '3200') continue;

        if (parentIDs.contains(item1.id) && item1.parentAccountId == 0) {
          continue;
        }

        if (item1.crdrNature == 'DR') {
          _dTotal += item1.balance;
        } else {
          _cTotal += item1.balance;
        }
      }
    }
    debitTotal = _dTotal;
    creditTotal = _cTotal;
    difference = debitTotal - creditTotal;
    if (isUpdate == true) update();
  }

  void onSelectMenu(String value) {
    if (isPlanExpired()) return;
    switch (value) {
      case 'Set Opening Balance':
        Routes.navigateTo(RouterGenProviders.setOpeningBalancePage);
        break;
      case 'Close Current FY':
        onCloseFinancialYear();
        break;
    }
  }

  void onNavAccountDetail(CoaCoaAccountHeaderCoaAccountDetail e,
      List<CoaCoaAccountHeaderCoaAccountDetail> coaAccountHeader) {
    unFocus();
    final parentAccount = coaAccountHeader.firstWhere(
        (element) => element.id == e.parentAccountId,
        orElse: () => CoaCoaAccountHeaderCoaAccountDetail()
          ..id = e.parentAccountId
          ..name = '');
    if (isSelectMode == true) {
      print('e.withSubaccountId ${e.withSubaccountId}');
      if (e.id == editId || e.withSubaccountId == 0) {
        return;
      }
      obtainContext?.call((context) {
        Navigator.of(context).pop(e);
      });
    } else {
      print('$parentAccount');
      Routes.navigateTo(RouterGenProviders.newAccountPage, params: {
        'data': e,
        'parentData': parentAccount,
      });
    }
  }

  void onSelectAsAt() {
    searchFocusNode.unfocus();
    obtainContext?.call((context) async {
      final result =
          await showDateTimeSelectBottomSheet(context, S.current.as_at, asAt);
      if (result != null) {
        searchController.clear();
        asAt = result;
        update();
        onRequestRefresh();
      }
    });
  }

  void onCloseFinancialYear() {
    obtainContext?.call((context) async {
      String message;

      bool isSuccess = await showCloseFinancialYearConfirmationBottomSheet(
        context,
        '${S.current.current_fy_}${DateTimeUtils.formatFinancialYearDate(Config.currentFY.startDate, Config.currentFY.endDate)}',
      );
      if (isSuccess) {
        await post(HttpCompanyService.closeFinancialYear(),
            autoHandler: AutoHandler.Toast,
            loadingTip: S.current.loading, onSuccess: (result) {
          message = result.data['msg'];
        });
        if (message != null) {
          await showGotItTipBottomSheet(context, message);
          await post(HttpCompanyService.getFinancialYears(),
              autoHandler: AutoHandler.Toast,
              loadingTip: S.current.loading, onSuccess: (result) async {
            List<CompanyFinancialYearEntity> fys =
                getEntityFromResult<List<CompanyFinancialYearEntity>>(result);
            RProvider.myProvider.globalMap[ConfigKey.currentFYs] = fys;
            await RProvider.myProvider.updateGlobalMap();
          });

          await post(
              HttpCompanyService.showCompanies(
                  Config.userProfile.defaultCompanyId),
              autoHandler: AutoHandler.Toast,
              loadingTip: S.current.loading, onSuccess: (result) async {
            CompanyEntity entity = getEntityFromResult<CompanyEntity>(result);
            RProvider.myProvider.globalMap[ConfigKey.currentCompany] = entity;
            await RProvider.myProvider.updateGlobalMap();
            asAt = DateTime.parse(Config.currentFY.endDate);
          });
          await post(dataFuture,
              autoHandler: AutoHandler.Toast,
              loadingTip: S.current.loading, onSuccess: (result) {
            data = transformData(
                getEntityFromResult<List<CoaByGroupEntity>>(result), false);
            update();
          });
          update();
        }
      }
    });
  }

  void onRequestRefresh() {
    post(dataFuture,
        autoHandler: AutoHandler.Toast,
        loadingTip: S.current.loading, onSuccess: (result) {
      data = transformData(
          getEntityFromResult<List<CoaByGroupEntity>>(result), false);
      update();
    });
  }

  @override
  FutureOr<List<CoaByGroupEntity>> transformData(
      List<CoaByGroupEntity> d, bool isCache) {
    if (isSelectMode == true) {
      for (var item in d) {
        item.coaAccountDetail
            .removeWhere((element) => element.parentAccountId != 0);
      }
    }

    for (var item in d) {
      parentIDs.addAll(item.coaAccountDetail
          .map((e) => e.parentAccountId)
          .where((parentId) => parentId != 0)
          .toSet()
          .toList());
    }

    formatTotal(d);
    return super.transformData(d, isCache);
  }
}
